package cn.dt.ymcc.service.impl;

import cn.dt.ymcc.doc.CourseDoc;
import cn.dt.ymcc.domain.*;
import cn.dt.ymcc.dto.CourseDto;
import cn.dt.ymcc.feigclient.MediaFeignClient;
import cn.dt.ymcc.feignclient.SearchsFeignClient;
import cn.dt.ymcc.mapper.CourseMapper;
import cn.dt.ymcc.result.JSONResult;
import cn.dt.ymcc.service.*;
import cn.dt.ymcc.util.AssertUtil;
import cn.dt.ymcc.util.StrUtils;
import cn.dt.ymcc.vo.CourseDetailVo;
import cn.dt.ymcc.vo.CourseItemVo;
import cn.dt.ymcc.vo.OrderInfoVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.junit.Assume;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale.dai
 * @since 2022-07-21
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private SearchsFeignClient searchsFeignClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ICourseChapterService courseChapterService;
    @Autowired
    private MediaFeignClient mediaFeignClient;

    /**
     * 1.参数校验（用jsr303）
     * 2.课程名称不能重复
     * 3.保存表数据
     *  3.1保存t_course表
     *  3.2保存t_course_detail表
     *  3.3保存t_course_market表
     *  3.4保存t_course_resource表
     * @param dto
     */
    @Override
    public void save(CourseDto dto) {
        Course course = dto.getCourse();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        List<Long> teacharIds = dto.getTeacharIds();
        //2.课程名称不能重复*****************开始******************
        Course courseTmp = selectByName(course.getName());
        AssertUtil.isNull(courseTmp,"课程已被注册，请重新输入课程名！！！");
        //2.课程名称不能重复*****************结束******************

        //3.保存表数据****************开始*************************
        course.setStatus(0);
        //@TODO 后面做了登录之后来补充
        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        // 整成stream
        StringBuilder sb = new StringBuilder();
        teachers.forEach(teacher -> {
            sb.append(teacher.getName()).append(",");
        });
        course.setTeacherNames(sb.toString());
        insert(course);
        //* 保存课程详情===========================
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);

        //* 保存课程销售===========================
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);

        //* 保存课程讲师===========================
        teacharIds.forEach(id->{
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            courseTeacherService.insert(courseTeacher);
        });
        //* 保存课程资源===========================
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);

        //* 初始化课程统计===========================
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);

        //课程类型表中的课程数+1======================
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        type.setTotalCount(type.getTotalCount() + 1);
        courseTypeService.updateById(type);
        //3.保存表数据****************结束*************************
    }



    /**
     * 第二步中通过名字查询课程的方法
     * @param name
     * @return
     */
    private Course selectByName(String name) {
        Wrapper<Course> tWrapper = new EntityWrapper<Course>();
        tWrapper.eq("name",name);
        Course course = selectOne(tWrapper);
        return course;
    }

    /**
     * 一.课程上架
     * 1.根据course是否存在
     * 2.修改course状态和上架时间
     * 3.保存到es中
     *  3.1在pojo-search的doc中确定要保存的字段
     *  3.2在search服务中保存doc
     *  3.3在api-search中写一个feign接口调用search保存doc
     *  3.4在此服务中注入api-search调用feign保存数据到ES
     *  ===================
     *  消息推广
     *  1.课程发布成功以后
     *      1.1使用rocketMq发送异步消息，成功--发送短信，失败提醒
     *
     *
     * @param courseId
     */
    @Override
    @Transactional
    public void onLineCourse(Long courseId) {
        //1.判断course是否存在-=======================
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"课程不存在，无法上线");
        //2.修改course状态和上架时间==================
        course.setStatus(Course.STATUS_ONLINE);
        course.setOnlineTime(new Date());
        updateById(course);
        //3.保存到es中==============================
        //3.1在pojo-search的doc中确定要保存的字段（chargeName在market表，typeName在CourseType中字段不一致要单独处理）
        //3.2在search服务中保存doc
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        CourseDoc doc = new CourseDoc();
        BeanUtils.copyProperties(course,doc);
        BeanUtils.copyProperties(courseMarket,doc);
        BeanUtils.copyProperties(courseSummary,doc);
        doc.setTypeName(courseType.getName());
        //3.3在api-search中写一个feign接口调用search保存doc
        //3.4在此服务中注入api-search调用feign保存数据到ES
        JSONResult result = searchsFeignClient.saveCourse(doc);
        //rocketMq消息生产者创建
        AssertUtil.isTrue(result.isSuccess(),"发布失败啦！！");
        //mq发送消息
     // sendMessage(course);

    }
    public void sendMessage(Course course){
        String CourseFileJsonStr = JSON.toJSONString(course);
        rocketMQTemplate.syncSend("course-topic:course-tags", CourseFileJsonStr);
    }

    /**
     * 课程下线，
     * 1.课程是否存在
     * 2.修改课程状态为下线0
     * 3.调用feign接口删除Es这条数据
     * @param courseId
     */
    @Override
    public void offLineCourse(Long courseId) {
        //1.判断course是否存在-=======================
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course, "课程不存在，无法下线");
        //2.修改课程状态为下线0========================
        course.setStatus(Course.STATUS_OFFLINE);
        updateById(course);
        //3.调用feign接口删除Es这条数据================
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        CourseDoc doc = new CourseDoc();
        BeanUtils.copyProperties(course, doc);
        BeanUtils.copyProperties(courseMarket, doc);
        BeanUtils.copyProperties(courseSummary, doc);
        doc.setTypeName(courseType.getName());
        //3.3在api-search中写一个feign接口调用search保存doc
        //3.4在此服务中注入api-search调用feign保存数据到ES
        JSONResult result = searchsFeignClient.deleteCourse(doc);
        AssertUtil.isTrue(result.isSuccess(), "下架失败啦！！");

    }

    /**
     * 课程详情页展示将以下数据传到前端，针对章节还需要将对应视频对上
     *     private Course course;
     *     private CourseMarket courseMarket;
     *     private CourseDetail courseDetail;
     *     private CourseSummary courseSummary;
     *      private Teacher teachers;
     *      private CourseChapter courseChapters;
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailVo CourseDetailData(Long courseId) {
        Long loginId = 3L;
        AssertUtil.isNotNull(courseId,"错误请求！！没有课程id");
        //查询Course
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"课程不存在");
        boolean online = course.getStatus() == 1;
        AssertUtil.isTrue(online,"课程未上架！！");
        //查询CourseMarket
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        //查CourseDetail
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        //查CourseSummary
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        //通过courseteacher中间表获取到教师id再去查teacher表
        Wrapper<CourseTeacher> courseTeacherWapper = new EntityWrapper<>();
        courseTeacherWapper.eq("course_id",courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(courseTeacherWapper);
        //省略的是流式编程获取到teacherIds
       // List<Long> teacherIds = courseTeachers.stream().map(teacher -> teacher.getTeacherId()).collect(Collectors.toList());
        List<Long> teacherIds = new ArrayList<>();
        for (CourseTeacher courseTeacher : courseTeachers) {
            Long teacherId = courseTeacher.getTeacherId();
            teacherIds.add(teacherId);
        }
        //查询Teacher
        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);
        //查询CourseChapter
        Wrapper<CourseChapter> chapterWrapper = new EntityWrapper<>();
        chapterWrapper.eq("course_id",courseId);
        List<CourseChapter> chapters = courseChapterService.selectList(chapterWrapper);
        for (CourseChapter chapter : chapters) {
            //将每个章节的视频传进去，调用feign接口
            //media服务准备个通过course_id查询视频的接口
            JSONResult result = mediaFeignClient.searchChepterMedia(chapter.getId());
            if(result.isSuccess()&&result.getData()!=null){
                List<MediaFile> mediaFiles = JSONObject.parseArray(result.getData().toString(), MediaFile.class);
                chapter.setMediaFiles(mediaFiles);
            }

        }
        CourseDetailVo vo = new CourseDetailVo();
        vo.setCourse(course);
        vo.setCourseMarket(courseMarket);
        vo.setCourseDetail(courseDetail);
        vo.setCourseSummary(courseSummary);
        vo.setTeachers(teachers);
        vo.setCourseChapters(chapters);
        return vo;
    }

    /**
     * 获取订单展示信息实现
     * 1.通过前端传的courseIds分割出id并转成list<Long>并查询出course和market对象
     * 2.业务分析
     *  2.1，判断课程是否上线，
     *  2.2 判断课程是否存在
     * 3，封装数据返回给前端
     * @param courseIds
     * @return
     */
    @Override
    public OrderInfoVo getOrderInfo(String courseIds) {

        List<Long> ids = StrUtils.splitStr2LongArr(courseIds);//分割出id
        Set<Long> setIds = ids.stream().collect(Collectors.toSet());
        BigDecimal totalAmount = new BigDecimal(0);
        ArrayList<CourseItemVo> courseInfos = new ArrayList<>();
        for (Long id : ids) {
            Course course = selectById(id);
            AssertUtil.isNotNull(course,"非法请求！！");
            boolean status = course.getStatus() == 1;
            //非法拿到未上架id
            AssertUtil.isTrue(status,"请求不合法");
            //查到的market
            CourseMarket market = courseMarketService.selectById(id);
           //将每一组课程和对应的支付信息封装到CourseItemVo
            CourseItemVo courseItemVo = new CourseItemVo(course, market);
            courseInfos.add(courseItemVo);
            totalAmount=totalAmount.add(market.getPrice());
        }
        return new OrderInfoVo(courseInfos,totalAmount);
    }
}
